#include "jkeyboardwidget.h"
#include "ui_jkeyboardwidget.h"

#include "inputmethod/jabstractcandidatepanel.h"
#include "inputmethod/jabstractinputpanel.h"
#include "jpanelmanager.h"

#include <QTECore/QTEGlobal>
#include <QKeyEvent>
#include <QScreen>
#include <QLabel>
#include <QTimer>

namespace QTE
{

class Q_DECL_HIDDEN JKeyboardWidgetPrivate : public QObject
{
public:
	JKeyboardWidgetPrivate(JPanelManager *manager, JKeyboardWidget *q_ptr);
	~JKeyboardWidgetPrivate();

public:
	void layoutAdaptation();
	void textInput(const QString &text);
	void keyInput(Qt::Key key);

private:
	void setWordPage();
	void setSymbolPage();

private:
	void sigSltInit();
	void mapperInit(const QObjectList &list);
	void mapperInit();
	void panelInit();

private: //slots
	void on_buttonPressed(QAbstractButton *button);
	void on_buttonRelease();

public:
	JKeyboardWidget *q_ptr;
	Ui::JKeyboardWidget *ui;

	bool m_numberKeyboardLock = false;
	bool m_lastIsNumberKey = false;

	JPanelManager *m_panelManager;
	QLabel *m_keyTipLabel;
	QSize m_lastSize;
};

#define TIP_MAGNIFICATION  6/5  /*不能加括号*/

JKeyboardWidgetPrivate::JKeyboardWidgetPrivate(JPanelManager *manager, JKeyboardWidget *q_ptr) :
	QObject(q_ptr), q_ptr(q_ptr),
	ui(new Ui::JKeyboardWidget),
	m_panelManager(manager),
	m_keyTipLabel(new QLabel("q"))
{
	q_ptr->blockSignals(true);

	ui->setupUi(q_ptr);
	ui->scrollArea->setAutoScrollBar(false);

	m_keyTipLabel->setAttribute(Qt::WA_ShowWithoutActivating);
	m_keyTipLabel->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint |
								  Qt::Tool | Qt::WindowDoesNotAcceptFocus);

	m_keyTipLabel->setObjectName(QString::fromUtf8("keyTipLabel"));
	m_keyTipLabel->setGeometry(QRect(10, 10, 40, 40));
	m_keyTipLabel->setMinimumSize(QSize(40, 40));
	m_keyTipLabel->setMaximumSize(QSize(40, 40));
	m_keyTipLabel->setStyleSheet(QString::fromUtf8("background-color:rgb(50,50,50); \n"
												 "border-color: rgb(255, 255, 255);\n"
												 "color: rgb(255, 255, 255);"));
	m_keyTipLabel->setFrameShape(QFrame::Box);
	m_keyTipLabel->setAlignment(Qt::AlignCenter);

	auto font = ui->j_tb_1->font();
	font.setPointSize(font.pointSize() * TIP_MAGNIFICATION);
	m_keyTipLabel->setFont(font);

	m_panelManager->setCurrentLanguage(LGG_GeneralEnglish);
	ui->tb_inputMethod->setText(inputMethodAbbreviation(LGG_GeneralEnglish));

	panelInit();
	sigSltInit();

	q_ptr->blockSignals(false);
}

JKeyboardWidgetPrivate::~JKeyboardWidgetPrivate()
{
	delete ui;
}

// 大小和位置自适应
static void __layoutAdaptation(QObjectList &list, qreal wRatio, qreal hRatio)
{
	for(auto &obj : list)
	{
		auto widget = J_OCT(QWidget*, obj);

		if( widget != nullptr )
		{
			auto panel = J_OCT(JAbstractInputPanel*, widget);
			if( panel )
				continue;

//			widget->setFixedSize(widget->width() * w_ratio, widget->height() * h_ratio);
			auto button = J_OCT(QAbstractButton*, widget);

			if( button != nullptr )
			{
				auto size = button->size();
				size.rwidth() *= wRatio;
				size.rheight() *= hRatio;

				if( button->property("scrollButton").toString() == "true" )
					size.rwidth() -= 2;

				button->setFixedSize(size);

				if( size.rwidth() > size.rheight() )
					size.rwidth() = size.rheight();
				else if( size.rheight() > size.rwidth() )
					size.rheight() = size.rwidth();

				button->setIconSize(size);
			}
			else
				__layoutAdaptation(J_CCT(QObjectList&, widget->children()), wRatio, hRatio);
		}
	}
}

// 大小自适应
void JKeyboardWidgetPrivate::layoutAdaptation()
{
	qreal wRatio = J_SCT(qreal, q_ptr->width()) / m_lastSize.width();
	qreal hRatio = J_SCT(qreal, q_ptr->height()) / m_lastSize.height();

	if( wRatio < 0.00000001 and hRatio < 0.00000001 )
		return ;

	__layoutAdaptation(J_CCT(QObjectList&, q_ptr->children()), wRatio, hRatio);
	m_lastSize = q_ptr->size();

	for(auto &obj : ui->widget_scrollAreaWidgetContents->children())
	{
		auto widget = J_OCT(QWidget*, obj);
		if( widget == nullptr )
			continue;

		if( widget->objectName().indexOf("j_tb_") != -1 )
			widget->setMinimumHeight(ui->j_tb_0_1->height() * 4 / 5);
		else
			widget->setMaximumHeight(2);
	}
}

void JKeyboardWidgetPrivate::textInput(const QString &text)
{
	if( text.isEmpty() )
		return ;

	auto panel = m_panelManager->candidatePanel();
	if( panel )
		panel->input(text);
}

void JKeyboardWidgetPrivate::keyInput(Qt::Key key)
{
	auto panel = m_panelManager->candidatePanel();
	if( panel )
		panel->input(key);
}

void JKeyboardWidgetPrivate::setWordPage()
{
	ui->wordStackedWidget->setCurrentWidget(m_panelManager->inputPanel());
	ui->tb_symbol->setText("!?#");

	emit q_ptr->panelChanged();
	emit q_ptr->autoPredicts();
}

void JKeyboardWidgetPrivate::setSymbolPage()
{
	ui->wordStackedWidget->setCurrentWidget(m_panelManager->symbolPanel());
	ui->tb_symbol->setText("abc");

	emit q_ptr->panelChanged();
}

void JKeyboardWidgetPrivate::sigSltInit()
{
	mapperInit();

	// 符号
	connect(ui->tb_symbol, &QToolButton::clicked, this, [this]()
	{
		if( ui->tb_symbol->text() == "abc" )
			setWordPage();
		else
		{
			setSymbolPage();
			m_panelManager->candidatePanel()->defaultInput();
		}
	});
	connect(ui->tb_symbol2, &QToolButton::clicked, this, [this]()
	{
		ui->numStackedWidget->setCurrentWidget(ui->widget_charPage);
		setSymbolPage();
	});

	// 数字
	connect(ui->tb_num, &QToolButton::clicked, this, [this]()
	{
		ui->numStackedWidget->setCurrentWidget(ui->widget_numPage);
		emit q_ptr->panelChanged();

		m_panelManager->candidatePanel()->defaultInput();
	});

	// 从数字返回
	connect(ui->tb_back, &QToolButton::clicked, this, [this]()
	{
		ui->numStackedWidget->setCurrentWidget(ui->widget_charPage);
		setWordPage();
	});

	// 输入法切换
	connect(ui->tb_inputMethod, &JVKButton::actionTrigger, this, [this](){

	});
	connect(ui->tb_inputMethod, &JVKButton::clicked, this, [this](){
		ui->tb_inputMethod->setText(m_panelManager->defaultChangeLanguage());
	});

	// 退出键盘
	connect(ui->tb_exit, &QToolButton::clicked, q_ptr, &JKeyboardWidget::hide);

	// 输入法改变
	connect(m_panelManager, &JPanelManager::languageChanged,
			this, &JKeyboardWidgetPrivate::panelInit);
}

void JKeyboardWidgetPrivate::mapperInit(const QObjectList &list)
{
	for(auto &obj : list)
	{
		auto widget = J_OCT(QWidget*, obj);
		if( widget == nullptr )
			continue;

		auto panel = J_OCT(JAbstractInputPanel*, widget);
		if( panel )
			continue;

		auto button = J_OCT(QAbstractButton*, widget);
		if( button == nullptr )
		{
			mapperInit(widget->children());
			continue ;
		}
		else if( button->objectName().indexOf("j_tb_") < 0 )
			continue ;

		button->installEventFilter(q_ptr);
		connect(button, &QAbstractButton::pressed,  this, [this, button](){on_buttonPressed(button);});
		connect(button, &QAbstractButton::clicked,  this, [this, button](){textInput(button->text());});
	}
}

void JKeyboardWidgetPrivate::mapperInit()
{
	mapperInit(q_ptr->children());

	// 空格
	connect(ui->tb_space,  &QToolButton::clicked, this, [this](){textInput(" ");});
	connect(ui->tb_space2, &QToolButton::clicked, this, [this](){textInput(" ");});

	// 回车
	connect(ui->tb_enter,  &QToolButton::clicked, this, [this](){keyInput(Qt::Key_Return);});
	connect(ui->tb_enter2, &QToolButton::clicked, this, [this](){keyInput(Qt::Key_Enter );});

	// ←↑↓→
	connect(ui->tb_left,  &QToolButton::clicked, this, [this](){keyInput(Qt::Key_Left );});
	connect(ui->tb_up,    &QToolButton::clicked, this, [this](){keyInput(Qt::Key_Up   );});
	connect(ui->tb_down,  &QToolButton::clicked, this, [this](){keyInput(Qt::Key_Down );});
	connect(ui->tb_right, &QToolButton::clicked, this, [this](){keyInput(Qt::Key_Right);});

	// 退格
	connect(ui->tb_backspace, &QToolButton::clicked, this, [this](){keyInput(Qt::Key_Backspace);});
}

void JKeyboardWidgetPrivate::panelInit()
{
	JAbstractInputPanel* list[] = { m_panelManager->inputPanel(), m_panelManager->symbolPanel() };

	for(auto &panel : list)
	{
		panel->disconnect(this);
		panel->reset();

		connect(panel, &JAbstractInputPanel::keyPressed, this, &JKeyboardWidgetPrivate::on_buttonPressed);
		connect(panel, &JAbstractInputPanel::keyRelease, this, &JKeyboardWidgetPrivate::on_buttonRelease);
		connect(panel, &JAbstractInputPanel::textInput, this, &JKeyboardWidgetPrivate::textInput);
		connect(panel, &JAbstractInputPanel::keyInput, this, &JKeyboardWidgetPrivate::keyInput);

		ui->wordStackedWidget->addWidget(panel);
	}

	auto candidatePanel = m_panelManager->candidatePanel();
	candidatePanel->disconnect(q_ptr);
	connect(candidatePanel, &JAbstractCandidatePanel::postKeyEvent, q_ptr, &JKeyboardWidget::input);

	ui->tb_space->setText(QString("[ %1 ]").arg(m_panelManager->panelName()));
	ui->j_tb_dot->setText(m_panelManager->fullStopText());
	ui->j_tb_comma->setText(m_panelManager->commaText());

	ui->wordStackedWidget->setCurrentWidget(m_panelManager->inputPanel());
	setWordPage();
}

void JKeyboardWidgetPrivate::on_buttonPressed(QAbstractButton *button)
{
	int width = button->width() * TIP_MAGNIFICATION;
	int height = button->height() * TIP_MAGNIFICATION;

	m_keyTipLabel->setFixedSize(width, height);
	auto pos = Gui::screenPos(button);

	pos.rx() -= (width - button->width()) >> 1;
	pos.ry() -= height;

	QString text = button->text();
	if( text.size() == 2 and text[0] == text[1] )
		text = text[0];

	m_keyTipLabel->setText(text);
	m_keyTipLabel->move(pos);
	m_keyTipLabel->show();
}

inline void JKeyboardWidgetPrivate::on_buttonRelease()
{
	m_keyTipLabel->hide();
}

/*------------------------------------------------------------------------------------------------------*/

JKeyboardWidget::JKeyboardWidget(JPanelManager *manager, QWidget *parent) :
	QWidget(parent),
	d_ptr(new JKeyboardWidgetPrivate(manager, this))
{
	d_ptr->m_lastSize = size();
}

JKeyboardWidget::~JKeyboardWidget()
{

}

void JKeyboardWidget::setNumberKeyboardLock(bool flag)
{
	d_ptr->m_lastIsNumberKey =
			d_ptr->ui->numStackedWidget->currentWidget() == d_ptr->ui->widget_numPage?
				true : false;

	d_ptr->m_numberKeyboardLock = flag;
	if( flag )
	{
		d_ptr->ui->numStackedWidget->setCurrentWidget(d_ptr->ui->widget_numPage);
		d_ptr->ui->tb_symbol2->setEnabled(false);
		d_ptr->ui->tb_back->setEnabled(false);
		d_ptr->ui->tb_back->setText("数字键盘");
		d_ptr->ui->tb_symbol2->setText("");
	}
}

JKeyboardWidget::Panel JKeyboardWidget::panel() const
{
	if( d_ptr->ui->numStackedWidget->currentWidget() == d_ptr->ui->widget_numPage )
		return Number;

	else if( d_ptr->ui->wordStackedWidget->currentWidget() == d_ptr->m_panelManager->inputPanel() )
		return Words;

	return Symbol;
}

void JKeyboardWidget::showEvent(QShowEvent *event)
{
	QWidget::showEvent(event);
	d_ptr->layoutAdaptation();

	if( d_ptr->m_numberKeyboardLock == false )
	{
		if( d_ptr->m_lastIsNumberKey == false )
			d_ptr->ui->numStackedWidget->setCurrentWidget(d_ptr->ui->widget_charPage);

		d_ptr->ui->tb_symbol2->setEnabled(true);
		d_ptr->ui->tb_back->setEnabled(true);
	}

	// 巨坑：在 EGLFS 平台下，禁止窗口抢占焦点后，第一次显示窗口可能还是会抢占焦点，提前show一下就解决了
	d_ptr->m_keyTipLabel->show();
	d_ptr->m_keyTipLabel->hide();
}

void JKeyboardWidget::resizeEvent(QResizeEvent *event)
{
	QWidget::resizeEvent(event);
	if( isVisible() )
		d_ptr->layoutAdaptation();
}

bool JKeyboardWidget::eventFilter(QObject *watched, QEvent *event)
{
	if( J_OCT(QAbstractButton*, watched) and event->type() == QEvent::MouseButtonRelease )
		d_ptr->m_keyTipLabel->hide();
	return false;
}

} //namespace QTE
